/*
 Copyright (C) 2009 are of bakabt
 boxtorrents, azureus, vuze, and java are copyrighted to their respective owner.

 This program is free software; you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation; version 2 of the License.

 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.

 You should have received a copy of the GNU General Public License
 along with this program; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
 */
package com.boxtorrents.azureus.action;

import java.io.Serializable;
import java.util.Arrays;
import java.util.Comparator;
import java.util.HashSet;
import java.util.Set;
import org.gudy.azureus2.core3.disk.DiskManagerFileInfo;
import org.gudy.azureus2.core3.disk.DiskManagerListener;
import org.gudy.azureus2.core3.disk.DiskManagerPiece;
import org.gudy.azureus2.plugins.PluginInterface;
import org.gudy.azureus2.plugins.download.Download;
import org.gudy.azureus2.plugins.download.DownloadAttributeListener;
import org.gudy.azureus2.plugins.download.DownloadCompletionListener;
import org.gudy.azureus2.plugins.download.DownloadManagerListener;
import org.gudy.azureus2.plugins.torrent.TorrentAttribute;
import org.gudy.azureus2.plugins.ui.menus.MenuItem;
import org.gudy.azureus2.plugins.ui.menus.MenuItemListener;
import org.gudy.azureus2.plugins.ui.tables.TableContextMenuItem;
import org.gudy.azureus2.plugins.ui.tables.TableManager;
import org.gudy.azureus2.plugins.ui.tables.TableRow;
import org.gudy.azureus2.pluginsimpl.local.disk.DiskManagerImpl;
import com.boxtorrents.azureus.BoxTorrentsPlugin;
import com.boxtorrents.azureus.Util;

/**
 * @author are of bakabt.com
 */
public class SerialDownload implements Serializable, DiskManagerListener {
	private static final long serialVersionUID = 4309630724266591850L;
	private static PluginInterface pi = BoxTorrentsPlugin.getPluginInterface();
	private static TorrentAttribute att = Util
	    .getTorrentAttribute("serialDownload");

	/**
	 * 
	 */
	public SerialDownload() {
		final DownloadAttributeListener downloadAttributeListener = new DownloadAttributeListener() {
			public void attributeEventOccurred(Download d, TorrentAttribute att, int i) {
				if (d == null || d.getDiskManager() == null) return;
				if (d.getDiskManager() instanceof DiskManagerImpl) {
					DiskManagerImpl dm = (DiskManagerImpl)d.getDiskManager();
					if (d.hasAttribute(att) && d.getAttribute(att) != null) {
						dm.getDiskmanager().addListener(SerialDownload.this);
					} else {
						dm.getDiskmanager().removeListener(SerialDownload.this);
						DiskManagerFileInfo[] files = dm.getDiskmanager().getFiles();
						for (DiskManagerFileInfo file : files) {
							if (file.isSkipped()) continue;
							file.setPriority(false);
						}
					}
				}
			}
		};

		pi.getDownloadManager().addListener(new DownloadManagerListener() {

			public void downloadAdded(Download d) {
				d.addAttributeListener(downloadAttributeListener, att,
				    DownloadAttributeListener.WRITTEN);
			}

			public void downloadRemoved(Download d) {
				d.removeAttributeListener(downloadAttributeListener, att,
				    DownloadAttributeListener.WRITTEN);
			}
		});
		pi.getDownloadManager().getGlobalDownloadEventNotifier()
		    .addCompletionListener(new DownloadCompletionListener() {
			    public void onCompletion(Download d) {
				    d.removeAttributeListener(downloadAttributeListener, att,
				        DownloadAttributeListener.WRITTEN);
			    }
		    });

		Set<TableContextMenuItem> mainMenu = new HashSet<TableContextMenuItem>();
		Set<MenuItem> mainMenu2 = BoxTorrentsPlugin.getConfPage().getMainMenu();
		for (MenuItem item : mainMenu2) {
			if (item instanceof TableContextMenuItem) {
				mainMenu.add((TableContextMenuItem)item);
			}
		}
		TableManager tableManager = pi.getUIManager().getTableManager();
		for (TableContextMenuItem parent : mainMenu) {
			if (parent.getTableID() == TableManager.TABLE_MYTORRENTS_INCOMPLETE
			    || parent.getTableID() == TableManager.TABLE_MYTORRENTS_INCOMPLETE_BIG) {

				TableContextMenuItem sep = tableManager.addContextMenuItem(parent,
				    "separator");
				sep.setStyle(MenuItem.STYLE_SEPARATOR);

				TableContextMenuItem item = tableManager.addContextMenuItem(parent,
				    "menu.boxmenu.serial.set");
				item.addListener(new MenuItemListener() {
					public void selected(MenuItem menu, Object obj) {
						if (obj instanceof TableRow) {
							selected(menu, new TableRow[] { (TableRow)obj });
						} else if (obj instanceof TableRow[]) {
							TableRow[] rows = (TableRow[])obj;
							for (TableRow row : rows) {
								if (row.getDataSource() instanceof Download) {
									Download d = (Download)row.getDataSource();
									d.setAttribute(att, "1");
								}
							}
						}
					}
				});
				TableContextMenuItem item2 = tableManager.addContextMenuItem(parent,
				    "menu.boxmenu.serial.unset");
				item2.addListener(new MenuItemListener() {
					public void selected(MenuItem menu, Object obj) {
						if (obj instanceof TableRow) {
							selected(menu, new TableRow[] { (TableRow)obj });
						} else if (obj instanceof TableRow[]) {
							TableRow[] rows = (TableRow[])obj;
							for (TableRow row : rows) {
								if (row.getDataSource() instanceof Download) {
									Download d = (Download)row.getDataSource();
									d.setAttribute(att, null);
								}
							}
						}
					}
				});

			}
		}
	}

	/**
	 * @inheritDoc
	 */
	public void fileAccessModeChanged(DiskManagerFileInfo arg0, int arg1, int arg2) {}

	/**
	 * @inheritDoc
	 */
	public void filePriorityChanged(DiskManagerFileInfo arg0) {}

	/**
	 * @inheritDoc
	 */
	public void pieceDoneChanged(DiskManagerPiece dmp) {
		// sort by filename
		DiskManagerFileInfo[] files = dmp.getManager().getFiles();
		Arrays.sort(files, new Comparator<DiskManagerFileInfo>() {
			public int compare(DiskManagerFileInfo o1, DiskManagerFileInfo o2) {
				return o1.getFile(false).compareTo(o2.getFile(false));
			}
		});

		// setting prio
		boolean mustSet = true;
		for (DiskManagerFileInfo file : files) {
			if (file.isSkipped()) continue;
			if (file.getDownloaded() >= file.getLength()) {
				file.setPriority(false);
				continue;
			}
			if (mustSet) {
				file.setPriority(true);
				mustSet = false;
			} else {
				file.setPriority(false);
			}
		}
	}

	/**
	 * @inheritDoc
	 */
	public void stateChanged(int arg0, int arg1) {}
}
